﻿// -----------------------------------------------------------------------
// <copyright file="VisitorBasePointCut.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Raop.Library.Aop.PointCut
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Roslyn.Compilers.CSharp;
    using Raop.Library.Tools;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public abstract class VisitorBasePointCut : SyntaxRewriter, IBasePointCut
    {
        protected bool Inherit<T>(NamedTypeSymbol type)
        {
            if (type.ToString() == typeof(T).FullName)
            {
                return true;
            }
            else if (type.BaseType != null)
            {
                return Inherit<T>(type.BaseType);
            }
            else
            {
                return false;
            }
        }

        protected SemanticModel model;

        protected Compilation compil;

        public SyntaxNode MakeAop(Compilation compil, SemanticModel model, SyntaxNode node)
        {
            this.compil = compil;
            this.model = model;

            return this.Visit(node);
        }

        private void Add(List<StatementSyntax> statements, string format, params object[] parameters)
        {
            statements.Add(Syntax.ParseStatement(String.Format(format, parameters)));
        }

        protected BlockSyntax AddAop(string attributeClassName, string className, string methodeName, BlockSyntax block)
        {
            var variableName = Generator.GenVariableName();
            var variableMethodName = Generator.GenVariableName();
            var variableElementName = Generator.GenVariableName();

            var list = new List<StatementSyntax>();

            // var methodeType = typeof(ParseSolution).GetMethod("Run");
            Add(list, "var {0} = typeof({1}).GetMethod(\"{2}\");", variableMethodName, className, methodeName);

            // var e = new Element();
            Add(list, "var {0} = new Raop.Element();", variableElementName);

            // e.Name = "Run",
            Add(list, "{0}.Name = \"{1}\";", variableElementName, methodeName);

            // var variable = new className()
            Add(list, "var {0} = new {1}();", variableName, attributeClassName);

            // variable.OnEnter(e);
            Add(list, "{0}.OnEnter({1});", variableName, variableElementName);

            list.Add(block);

            // variable.OnExit(e);
            Add(list, "{0}.OnExit({1});", variableName, variableElementName);

            return Syntax.Block(statements: Syntax.List<StatementSyntax>(list));
        }

    }
}
